#pragma once
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <queue>
#include "Task.hpp"
using namespace std;
template <class T>
class Block_Queue
{
private:
    bool IsEmpty()
    {
        return _q.size() == 0;
    }
    bool IsFull()
    {
        return _capacity == _q.size();
    }

public:
    Block_Queue(size_t capacity = 5)
        : _capacity(capacity)
    {
        pthread_mutex_init(&_mtx, nullptr);
        pthread_cond_init(&_Empty, nullptr);
        pthread_cond_init(&_Full, nullptr);
    }

    void push(const T &pushin)
    {
        pthread_mutex_lock(&_mtx);

        while (IsFull())
            pthread_cond_wait(&_Full, &_mtx);
        _q.push(pushin);
        //cout<<"生产成功 "<<pushin<<" ";
        //cout <<pthread_self() <<" productor: "<< pushin._x << "+" << pushin._y << "=?" << endl;
        pthread_mutex_unlock(&_mtx);
        pthread_cond_signal(&_Empty);
    }

    void pop(T &ret)
    {
        pthread_mutex_lock(&_mtx);
        while (IsEmpty())
            pthread_cond_wait(&_Empty, &_mtx);
        ret = _q.front();
        _q.pop();
        //cout<<"消费成功 "<<ret<<" ";
        //cout << pthread_self() <<" consumer: "<< ret._x << "+" << ret._y << "=" << ret() << endl;
        pthread_mutex_unlock(&_mtx);
        pthread_cond_signal(&_Full);
    }

    ~Block_Queue()
    {
        pthread_mutex_destroy(&_mtx);
        pthread_cond_destroy(&_Empty);
        pthread_cond_destroy(&_Full);
    }

public:
    queue<T> _q;
    size_t _capacity;
    pthread_mutex_t _mtx;
    pthread_cond_t _Empty;
    pthread_cond_t _Full;
};